/*
 * Copyright (c) 2024, Composite USB Device
 *
 * SPDX-License-Identifier: Apache-2.0
 */
#include <rtdevice.h>
#include "board.h"
#include "usbd_core.h"
#include "usbd_audio.h"
#include "usbd_hid.h"
#include "usb_util.h"
#include "trace_log.h"


/*************************************************************************************/
#define USBD_VID           0x303A
#define USBD_PID           0x2986
// #define USBD_MAX_POWER     100
// #define USBD_LANGID_STRING 1033

/* Display设备端点定义 */
#define DISPLAY_IN_EP  0x81
#define DISPLAY_OUT_EP 0x01
#define DISPLAY_EP_SIZE 512

#define MAX_DISP_PAYLOAD_SIZE (16384)

/* Audio设备端点定义 */
#define AUDIO_OUT_EP 0x02
#define AUDIO_OUT_PACKET   192
#define AUDIO_OUT_FU_ID 0x05

#define AUDIO_OUT_FEEDBACK_EP 0x83
#define USING_FEEDBACK 0
#define FEEDBACK_ENDP_PACKET_SIZE 4

/* Hid设备端点定义 */
#define HID_INT_EP          0x84
#define HID_INT_EP_SIZE     512
#define HID_INT_EP_INTERVAL 10




/*************************************************************************************/
#define HID_STATE_IDLE 0
#define HID_STATE_BUSY 1

/*!< hid state ! Data can be sent only when state is idle  */
static volatile uint8_t hid_state = HID_STATE_IDLE;

/* Audio设备缓冲区 */
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t audio_read_buffer[AUDIO_OUT_PACKET];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t s_speaker_feedback_buffer[4];

/* Display设备缓冲区 */
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t display_read_buffer[MAX_DISP_PAYLOAD_SIZE];

/* Audio设备变量 */
volatile bool audio_rx_flag = 0;
volatile uint32_t s_speaker_sample_rate;












/*************************************************************************************/
static const uint8_t device_descriptor[] = {
    0x12,        // bLength
    0x01,        // bDescriptorType (Device)
    0x00, 0x02,  // bcdUSB 2.00
    0xEF,        // bDeviceClass 
    0x02,        // bDeviceSubClass 
    0x01,        // bDeviceProtocol 
    0x40,        // bMaxPacketSize0 64
    WBVAL(USBD_VID),  // idVendor 0x303A
    WBVAL(USBD_PID),  // idProduct 0x2986
    0x00, 0x01,  // bcdDevice 2.00
    0x01,        // iManufacturer (String Index)
    0x02,        // iProduct (String Index)
    0x03,        // iSerialNumber (String Index)
    0x01,        // bNumConfigurations 1
    
    // 18 bytes    
};

#if USING_FEEDBACK == 0
static const uint8_t config_descriptor[] = {
    0x09,        // bLength
    0x02,        // bDescriptorType (Configuration)
    0xA6, 0x00,  // wTotalLength 166
    0x04,        // bNumInterfaces 4
    0x01,        // bConfigurationValue
    0x00,        // iConfiguration (String Index)
    0x80,        // bmAttributes
    0x32,        // bMaxPower 100mA
    
    0x09,        // bLength
    0x04,        // bDescriptorType (Interface)
    0x00,        // bInterfaceNumber 0
    0x00,        // bAlternateSetting
    0x02,        // bNumEndpoints 2
    0xFF,        // bInterfaceClass
    0x00,        // bInterfaceSubClass
    0x00,        // bInterfaceProtocol
    0x02,        // iInterface (String Index)
    
    0x07,        // bLength
    0x05,        // bDescriptorType (Endpoint)
    0x81,        // bEndpointAddress (IN/D2H)
    0x02,        // bmAttributes (Bulk)
    0x00, 0x02,  // wMaxPacketSize 512
    0x00,        // bInterval 0 (unit depends on device speed)
    
    0x07,        // bLength
    0x05,        // bDescriptorType (Endpoint)
    0x01,        // bEndpointAddress (OUT/H2D)
    0x02,        // bmAttributes (Bulk)
    0x00, 0x02,  // wMaxPacketSize 512
    0x00,        // bInterval 0 (unit depends on device speed)
    
    0x08,        // bLength
    0x0B,        // bDescriptorType (Interface Association)
    0x01,        // bFirstInterface 1
    0x02,        // bNumInterfaces 2
    0x01,        // bFunctionClass (Audio)
    0x01,        // bFunctionSubClass 0x01
    0x00,        // bFunctionProtocal 0x00
    0x00,        // iFunction

    0x09,        // bLength
    0x04,        // bDescriptorType (Interface)
    0x01,        // bInterfaceNumber 1
    0x00,        // bAlternateSetting
    0x00,        // bNumEndpoints 0
    0x01,        // bInterfaceClass (Audio)
    0x01,        // bInterfaceSubClass (Audio Control)
    0x00,        // bInterfaceProtocol
    0x04,        // iInterface (String Index)
    
    0x09,        // bLength
    0x24,        // bDescriptorType (See Next Line)
    0x01,        // bDescriptorSubtype (CS_INTERFACE -> HEADER)
    0x00, 0x01,  // bcdADC 1.00
    0x28, 0x00,  // wTotalLength 40
    0x01,        // binCollection 0x01
    0x02,        // baInterfaceNr 2
    
    0x0C,        // bLength
    0x24,        // bDescriptorType (See Next Line)
    0x02,        // bDescriptorSubtype (CS_INTERFACE -> INPUT_TERMINAL)
    0x04,        // bTerminalID
    0x01, 0x01,  // wTerminalType (USB Streaming)
    0x00,        // bAssocTerminal
    0x02,        // bNrChannels 2
    0x03, 0x00,  // wChannelConfig (Left and Right Front)
    0x00,        // iChannelNames
    0x00,        // iTerminal
    
    0x0A,        // bLength
    0x24,        // bDescriptorType (See Next Line)
    0x06,        // bDescriptorSubtype (CS_INTERFACE -> FEATURE_UNIT)
    0x05,        // bUnitID
    0x04,        // bSourceID
    0x01,        // bControlSize 1
    0x03, 0x00,  // bmaControls[0] (Mute,Volume)
    0x00, 0x00,  // bmaControls[1] (None)
    
    0x09,        // bLength
    0x24,        // bDescriptorType (See Next Line)
    0x03,        // bDescriptorSubtype (CS_INTERFACE -> OUTPUT_TERMINAL)
    0x06,        // bTerminalID
    0x01, 0x03,  // wTerminalType (Speaker)
    0x00,        // bAssocTerminal
    0x05,        // bSourceID
    0x00,        // iTerminal
    
    0x09,        // bLength
    0x04,        // bDescriptorType (Interface)
    0x02,        // bInterfaceNumber 2
    0x00,        // bAlternateSetting
    0x00,        // bNumEndpoints 0
    0x01,        // bInterfaceClass (Audio)
    0x02,        // bInterfaceSubClass (Audio Streaming)
    0x00,        // bInterfaceProtocol
    0x00,        // iInterface (String Index)
    
    0x09,        // bLength
    0x04,        // bDescriptorType (Interface)
    0x02,        // bInterfaceNumber 2
    0x01,        // bAlternateSetting
    0x01,        // bNumEndpoints 1
    0x01,        // bInterfaceClass (Audio)
    0x02,        // bInterfaceSubClass (Audio Streaming)
    0x00,        // bInterfaceProtocol
    0x00,        // iInterface (String Index)
    
    0x07,        // bLength
    0x24,        // bDescriptorType (See Next Line)
    0x01,        // bDescriptorSubtype (CS_INTERFACE -> AS_GENERAL)
    0x04,        // bTerminalLink
    0x01,        // bDelay 1
    0x01, 0x00,  // wFormatTag (PCM)
    
    0x0B,        // bLength
    0x24,        // bDescriptorType (See Next Line)
    0x02,        // bDescriptorSubtype (CS_INTERFACE -> FORMAT_TYPE)
    0x01,        // bFormatType 1
    0x02,        // bNrChannels (Stereo)
    0x02,        // bSubFrameSize 2
    0x10,        // bBitResolution 16
    0x01,        // bSamFreqType 1
    0x80, 0xBB, 0x00,  // tSamFreq[1] 48000 Hz
    
    0x09,        // bLength
    0x05,        // bDescriptorType (See Next Line)
    0x02,        // bEndpointAddress (OUT/H2D)
    0x09,        // bmAttributes (Isochronous, Adaptive, Data EP)
    0xC0, 0x00,  // wMaxPacketSize 192
    0x04,        // bInterval 4 (unit depends on device speed)
    0x00,        // bRefresh
    0x00,        // bSyncAddress
    
    0x07,        // bLength
    0x25,        // bDescriptorType (See Next Line)
    0x01,        // bDescriptorSubtype (CS_ENDPOINT -> EP_GENERAL)
    0x01,        // bmAttributes (Sampling Freq Control)
    0x00,        // bLockDelayUnits
    0x00, 0x00,  // wLockDelay 0
    
    0x09,        // bLength
    0x04,        // bDescriptorType (Interface)
    0x03,        // bInterfaceNumber 3
    0x00,        // bAlternateSetting
    0x01,        // bNumEndpoints 1
    0x03,        // bInterfaceClass
    0x00,        // bInterfaceSubClass
    0x00,        // bInterfaceProtocol
    0x05,        // iInterface (String Index)
    
    0x09,        // bLength
    0x21,        // bDescriptorType (HID)
    0x11, 0x01,  // bcdHID 1.11
    0x00,        // bCountryCode
    0x01,        // bNumDescriptors
    0x22,        // bDescriptorType[0] (HID)
    0x76, 0x01,  // wDescriptorLength[0] 374
    
    0x07,        // bLength
    0x05,        // bDescriptorType (Endpoint)
    0x84,        // bEndpointAddress (IN/D2H)
    0x03,        // bmAttributes (Interrupt)
    0x00, 0x02,  // wMaxPacketSize 512
    0x0A,        // bInterval 10 (unit depends on device speed)
    
    // 166 bytes    
};
# else
static const uint8_t config_descriptor[] = {
    0x09,        // bLength
    0x02,        // bDescriptorType (Configuration)
    0xAF, 0x00,  // wTotalLength 175
    0x04,        // bNumInterfaces 4
    0x01,        // bConfigurationValue
    0x00,        // iConfiguration (String Index)
    0x80,        // bmAttributes
    0x32,        // bMaxPower 100mA
    
    0x09,        // bLength
    0x04,        // bDescriptorType (Interface)
    0x00,        // bInterfaceNumber 0
    0x00,        // bAlternateSetting
    0x02,        // bNumEndpoints 2
    0xFF,        // bInterfaceClass
    0x00,        // bInterfaceSubClass
    0x00,        // bInterfaceProtocol
    0x00,        // iInterface (String Index)
    
    0x07,        // bLength
    0x05,        // bDescriptorType (Endpoint)
    0x84,        // bEndpointAddress (IN/D2H)
    0x02,        // bmAttributes (Bulk)
    0x00, 0x02,  // wMaxPacketSize 512
    0x00,        // bInterval 0 (unit depends on device speed)
    
    0x07,        // bLength
    0x05,        // bDescriptorType (Endpoint)
    0x05,        // bEndpointAddress (OUT/H2D)
    0x02,        // bmAttributes (Bulk)
    0x00, 0x02,  // wMaxPacketSize 512
    0x00,        // bInterval 0 (unit depends on device speed)
    
    0x08,        // bLength
    0x0B,        // bDescriptorType (Interface Association)
    0x01,        // bFirstInterface 1
    0x02,        // bNumInterfaces 2
    0x01,        // bFunctionClass (Audio)
    0x01,        // bFunctionSubClass 0x01
    0x00,        // bFunctionProtocal 0x00
    0x00,        // iFunction

    0x09,        // bLength
    0x04,        // bDescriptorType (Interface)
    0x01,        // bInterfaceNumber 1
    0x00,        // bAlternateSetting
    0x00,        // bNumEndpoints 0
    0x01,        // bInterfaceClass (Audio)
    0x01,        // bInterfaceSubClass (Audio Control)
    0x00,        // bInterfaceProtocol
    0x04,        // iInterface (String Index)
    
    0x09,        // bLength
    0x24,        // bDescriptorType (See Next Line)
    0x01,        // bDescriptorSubtype (CS_INTERFACE -> HEADER)
    0x00, 0x01,  // bcdADC 1.00
    0x28, 0x00,  // wTotalLength 40
    0x01,        // binCollection 0x01
    0x02,        // baInterfaceNr 2
    
    0x0C,        // bLength
    0x24,        // bDescriptorType (See Next Line)
    0x02,        // bDescriptorSubtype (CS_INTERFACE -> INPUT_TERMINAL)
    0x04,        // bTerminalID
    0x01, 0x01,  // wTerminalType (USB Streaming)
    0x00,        // bAssocTerminal
    0x02,        // bNrChannels 2
    0x03, 0x00,  // wChannelConfig (Left and Right Front)
    0x00,        // iChannelNames
    0x00,        // iTerminal
    
    0x0A,        // bLength
    0x24,        // bDescriptorType (See Next Line)
    0x06,        // bDescriptorSubtype (CS_INTERFACE -> FEATURE_UNIT)
    0x05,        // bUnitID
    0x04,        // bSourceID
    0x01,        // bControlSize 1
    0x03, 0x00,  // bmaControls[0] (Mute,Volume)
    0x00, 0x00,  // bmaControls[1] (None)
    
    0x09,        // bLength
    0x24,        // bDescriptorType (See Next Line)
    0x03,        // bDescriptorSubtype (CS_INTERFACE -> OUTPUT_TERMINAL)
    0x06,        // bTerminalID
    0x01, 0x03,  // wTerminalType (Speaker)
    0x00,        // bAssocTerminal
    0x05,        // bSourceID
    0x00,        // iTerminal
    
    0x09,        // bLength
    0x04,        // bDescriptorType (Interface)
    0x02,        // bInterfaceNumber 2
    0x00,        // bAlternateSetting
    0x00,        // bNumEndpoints 0
    0x01,        // bInterfaceClass (Audio)
    0x02,        // bInterfaceSubClass (Audio Streaming)
    0x00,        // bInterfaceProtocol
    0x00,        // iInterface (String Index)
    
    0x09,        // bLength
    0x04,        // bDescriptorType (Interface)
    0x02,        // bInterfaceNumber 2
    0x01,        // bAlternateSetting
    0x02,        // bNumEndpoints 2
    0x01,        // bInterfaceClass (Audio)
    0x02,        // bInterfaceSubClass (Audio Streaming)
    0x00,        // bInterfaceProtocol
    0x00,        // iInterface (String Index)
    
    0x07,        // bLength
    0x24,        // bDescriptorType (See Next Line)
    0x01,        // bDescriptorSubtype (CS_INTERFACE -> AS_GENERAL)
    0x04,        // bTerminalLink
    0x01,        // bDelay 1
    0x01, 0x00,  // wFormatTag (PCM)
    
    0x0B,        // bLength
    0x24,        // bDescriptorType (See Next Line)
    0x02,        // bDescriptorSubtype (CS_INTERFACE -> FORMAT_TYPE)
    0x01,        // bFormatType 1
    0x02,        // bNrChannels (Stereo)
    0x02,        // bSubFrameSize 2
    0x10,        // bBitResolution 16
    0x01,        // bSamFreqType 1
    0x40, 0x1F, 0x00,  // tSamFreq[1] 8000 Hz
    
    0x09,        // bLength
    0x05,        // bDescriptorType (See Next Line)
    0x01,        // bEndpointAddress (OUT/H2D)
    0x05,        // bmAttributes (Isochronous, Async, Data EP)
    0x20, 0x00,  // wMaxPacketSize 32
    0x04,        // bInterval 4 (unit depends on device speed)
    0x00,        // bRefresh
    0x82,        // bSyncAddress
    
    0x07,        // bLength
    0x25,        // bDescriptorType (See Next Line)
    0x01,        // bDescriptorSubtype (CS_ENDPOINT -> EP_GENERAL)
    0x01,        // bmAttributes (Sampling Freq Control)
    0x00,        // bLockDelayUnits
    0x00, 0x00,  // wLockDelay 0
    
    0x09,        // bLength
    0x05,        // bDescriptorType (See Next Line)
    0x82,        // bEndpointAddress (IN/D2H)
    0x11,        // bmAttributes (Isochronous, No Sync, Feedback EP)
    0x04, 0x00,  // wMaxPacketSize 4
    0x04,        // bInterval 4 (unit depends on device speed)
    0x03,        // bRefresh
    0x00,        // bSyncAddress
    
    0x09,        // bLength
    0x04,        // bDescriptorType (Interface)
    0x03,        // bInterfaceNumber 3
    0x00,        // bAlternateSetting
    0x01,        // bNumEndpoints 1
    0x03,        // bInterfaceClass
    0x00,        // bInterfaceSubClass
    0x00,        // bInterfaceProtocol
    0x05,        // iInterface (String Index)
    
    0x09,        // bLength
    0x21,        // bDescriptorType (HID)
    0x11, 0x01,  // bcdHID 1.11
    0x00,        // bCountryCode
    0x01,        // bNumDescriptors
    0x22,        // bDescriptorType[0] (HID)
    0x76, 0x01,  // wDescriptorLength[0] 374
    
    0x07,        // bLength
    0x05,        // bDescriptorType (Endpoint)
    0x83,        // bEndpointAddress (IN/D2H)
    0x03,        // bmAttributes (Interrupt)
    0x00, 0x02,  // wMaxPacketSize 512
    0x0A,        // bInterval 10 (unit depends on device speed)
    
    // 175 bytes    
};
# endif



#define HID_REPORT_DESC_SIZE 374
static const uint8_t hid_report_desc[] = {
    0x05, 0x0D,        // Usage Page (Digitizer)
    0x09, 0x04,        // Usage (Touch Screen)
    0xA1, 0x01,        // Collection (Application)
    0x85, 0x01,        //   Report ID (1)
    0x09, 0x42,        //   Usage (Tip Switch)
    0xA1, 0x02,        //   Collection (Logical)
    0x09, 0x42,        //     Usage (Tip Switch)
    0x15, 0x00,        //     Logical Minimum (0)
    0x25, 0x01,        //     Logical Maximum (1)
    0x75, 0x01,        //     Report Size (1)
    0x95, 0x01,        //     Report Count (1)
    0x81, 0x02,        //     Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
    0x95, 0x07,        //     Report Count (7)
    0x81, 0x01,        //     Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
    0x75, 0x08,        //     Report Size (8)
    0x09, 0x51,        //     Usage (0x51)
    0x95, 0x01,        //     Report Count (1)
    0x81, 0x02,        //     Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
    0x05, 0x01,        //     Usage Page (Generic Desktop Ctrls)
    0x26, 0x00, 0x04,  //     Logical Maximum (1024)
    0x75, 0x10,        //     Report Size (16)
    0x55, 0x0E,        //     Unit Exponent (-2)
    0x65, 0x13,        //     Unit (System: English Linear, Length: Centimeter)
    0x09, 0x30,        //     Usage (X)
    0x35, 0x00,        //     Physical Minimum (0)
    0x46, 0x00, 0x04,  //     Physical Maximum (1024)
    0x81, 0x02,        //     Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
    0x26, 0x40, 0x02,  //     Logical Maximum (576)
    0x46, 0x40, 0x02,  //     Physical Maximum (576)
    0x09, 0x31,        //     Usage (Y)
    0x81, 0x02,        //     Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
    0x05, 0x0D,        //     Usage Page (Digitizer)
    0x09, 0x48,        //     Usage (0x48)
    0x09, 0x49,        //     Usage (0x49)
    0x95, 0x02,        //     Report Count (2)
    0x81, 0x02,        //     Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
    0xC0,              //   End Collection
    0x09, 0x42,        //   Usage (Tip Switch)
    0xA1, 0x02,        //   Collection (Logical)
    0x09, 0x42,        //     Usage (Tip Switch)
    0x15, 0x00,        //     Logical Minimum (0)
    0x25, 0x01,        //     Logical Maximum (1)
    0x75, 0x01,        //     Report Size (1)
    0x95, 0x01,        //     Report Count (1)
    0x81, 0x02,        //     Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
    0x95, 0x07,        //     Report Count (7)
    0x81, 0x01,        //     Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
    0x75, 0x08,        //     Report Size (8)
    0x09, 0x51,        //     Usage (0x51)
    0x95, 0x01,        //     Report Count (1)
    0x81, 0x02,        //     Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
    0x05, 0x01,        //     Usage Page (Generic Desktop Ctrls)
    0x26, 0x00, 0x04,  //     Logical Maximum (1024)
    0x75, 0x10,        //     Report Size (16)
    0x55, 0x0E,        //     Unit Exponent (-2)
    0x65, 0x13,        //     Unit (System: English Linear, Length: Centimeter)
    0x09, 0x30,        //     Usage (X)
    0x35, 0x00,        //     Physical Minimum (0)
    0x46, 0x00, 0x04,  //     Physical Maximum (1024)
    0x81, 0x02,        //     Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
    0x26, 0x40, 0x02,  //     Logical Maximum (576)
    0x46, 0x40, 0x02,  //     Physical Maximum (576)
    0x09, 0x31,        //     Usage (Y)
    0x81, 0x02,        //     Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
    0x05, 0x0D,        //     Usage Page (Digitizer)
    0x09, 0x48,        //     Usage (0x48)
    0x09, 0x49,        //     Usage (0x49)
    0x95, 0x02,        //     Report Count (2)
    0x81, 0x02,        //     Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
    0xC0,              //   End Collection
    0x09, 0x42,        //   Usage (Tip Switch)
    0xA1, 0x02,        //   Collection (Logical)
    0x09, 0x42,        //     Usage (Tip Switch)
    0x15, 0x00,        //     Logical Minimum (0)
    0x25, 0x01,        //     Logical Maximum (1)
    0x75, 0x01,        //     Report Size (1)
    0x95, 0x01,        //     Report Count (1)
    0x81, 0x02,        //     Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
    0x95, 0x07,        //     Report Count (7)
    0x81, 0x01,        //     Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
    0x75, 0x08,        //     Report Size (8)
    0x09, 0x51,        //     Usage (0x51)
    0x95, 0x01,        //     Report Count (1)
    0x81, 0x02,        //     Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
    0x05, 0x01,        //     Usage Page (Generic Desktop Ctrls)
    0x26, 0x00, 0x04,  //     Logical Maximum (1024)
    0x75, 0x10,        //     Report Size (16)
    0x55, 0x0E,        //     Unit Exponent (-2)
    0x65, 0x13,        //     Unit (System: English Linear, Length: Centimeter)
    0x09, 0x30,        //     Usage (X)
    0x35, 0x00,        //     Physical Minimum (0)
    0x46, 0x00, 0x04,  //     Physical Maximum (1024)
    0x81, 0x02,        //     Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
    0x26, 0x40, 0x02,  //     Logical Maximum (576)
    0x46, 0x40, 0x02,  //     Physical Maximum (576)
    0x09, 0x31,        //     Usage (Y)
    0x81, 0x02,        //     Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
    0x05, 0x0D,        //     Usage Page (Digitizer)
    0x09, 0x48,        //     Usage (0x48)
    0x09, 0x49,        //     Usage (0x49)
    0x95, 0x02,        //     Report Count (2)
    0x81, 0x02,        //     Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
    0xC0,              //   End Collection
    0x09, 0x42,        //   Usage (Tip Switch)
    0xA1, 0x02,        //   Collection (Logical)
    0x09, 0x42,        //     Usage (Tip Switch)
    0x15, 0x00,        //     Logical Minimum (0)
    0x25, 0x01,        //     Logical Maximum (1)
    0x75, 0x01,        //     Report Size (1)
    0x95, 0x01,        //     Report Count (1)
    0x81, 0x02,        //     Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
    0x95, 0x07,        //     Report Count (7)
    0x81, 0x01,        //     Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
    0x75, 0x08,        //     Report Size (8)
    0x09, 0x51,        //     Usage (0x51)
    0x95, 0x01,        //     Report Count (1)
    0x81, 0x02,        //     Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
    0x05, 0x01,        //     Usage Page (Generic Desktop Ctrls)
    0x26, 0x00, 0x04,  //     Logical Maximum (1024)
    0x75, 0x10,        //     Report Size (16)
    0x55, 0x0E,        //     Unit Exponent (-2)
    0x65, 0x13,        //     Unit (System: English Linear, Length: Centimeter)
    0x09, 0x30,        //     Usage (X)
    0x35, 0x00,        //     Physical Minimum (0)
    0x46, 0x00, 0x04,  //     Physical Maximum (1024)
    0x81, 0x02,        //     Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
    0x26, 0x40, 0x02,  //     Logical Maximum (576)
    0x46, 0x40, 0x02,  //     Physical Maximum (576)
    0x09, 0x31,        //     Usage (Y)
    0x81, 0x02,        //     Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
    0x05, 0x0D,        //     Usage Page (Digitizer)
    0x09, 0x48,        //     Usage (0x48)
    0x09, 0x49,        //     Usage (0x49)
    0x95, 0x02,        //     Report Count (2)
    0x81, 0x02,        //     Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
    0xC0,              //   End Collection
    0x09, 0x42,        //   Usage (Tip Switch)
    0xA1, 0x02,        //   Collection (Logical)
    0x09, 0x42,        //     Usage (Tip Switch)
    0x15, 0x00,        //     Logical Minimum (0)
    0x25, 0x01,        //     Logical Maximum (1)
    0x75, 0x01,        //     Report Size (1)
    0x95, 0x01,        //     Report Count (1)
    0x81, 0x02,        //     Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
    0x95, 0x07,        //     Report Count (7)
    0x81, 0x01,        //     Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
    0x75, 0x08,        //     Report Size (8)
    0x09, 0x51,        //     Usage (0x51)
    0x95, 0x01,        //     Report Count (1)
    0x81, 0x02,        //     Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
    0x05, 0x01,        //     Usage Page (Generic Desktop Ctrls)
    0x26, 0x00, 0x04,  //     Logical Maximum (1024)
    0x75, 0x10,        //     Report Size (16)
    0x55, 0x0E,        //     Unit Exponent (-2)
    0x65, 0x13,        //     Unit (System: English Linear, Length: Centimeter)
    0x09, 0x30,        //     Usage (X)
    0x35, 0x00,        //     Physical Minimum (0)
    0x46, 0x00, 0x04,  //     Physical Maximum (1024)
    0x81, 0x02,        //     Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
    0x26, 0x40, 0x02,  //     Logical Maximum (576)
    0x46, 0x40, 0x02,  //     Physical Maximum (576)
    0x09, 0x31,        //     Usage (Y)
    0x81, 0x02,        //     Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
    0x05, 0x0D,        //     Usage Page (Digitizer)
    0x09, 0x48,        //     Usage (0x48)
    0x09, 0x49,        //     Usage (0x49)
    0x95, 0x02,        //     Report Count (2)
    0x81, 0x02,        //     Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
    0xC0,              //   End Collection
    0x09, 0x54,        //   Usage (0x54)
    0x25, 0x7F,        //   Logical Maximum (127)
    0x95, 0x01,        //   Report Count (1)
    0x75, 0x08,        //   Report Size (8)
    0x81, 0x02,        //   Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
    0x85, 0x02,        //   Report ID (2)
    0x09, 0x55,        //   Usage (0x55)
    0x95, 0x01,        //   Report Count (1)
    0x25, 0x10,        //   Logical Maximum (16)
    0xB1, 0x02,        //   Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
    0xC0,              // End Collection
    
    // 374 bytes    
};


/* 设备限定描述符 */
static const uint8_t device_quality_descriptor[] = {
    0x0A,        // bLength
    0x06,        // bDescriptorType (Device Qualifier)
    0x00, 0x02,  // bcdUSB 2.00
    0x00,        // bDeviceClass (Use class information in the Interface Descriptors)
    0x00,        // bDeviceSubClass 
    0x00,        // bDeviceProtocol 
    0x40,        // bMaxPacketSize0 64
    0x00,        // bNumConfigurations 0
    0x00,        // bReserved
    
    // 10 bytes
};

/* 字符串描述符 */
static const char *string_descriptors[] = {
    (const char[]){ 0x09, 0x04 },           /* Langid */
    "ch32",                                 /* Manufacturer */
    "ch32_R800x480_Ergb16_Fps15_Bl128",      /* Product */
    // "ch32_R800x480_Ejpg75_Fps30_Bl128",      /* Product */
    "2022123456",                           /* Serial Number */
    "ch32_uac_v1p0",
    "ch32_hid_tp"
};

/* 描述符回调函数 */
static const uint8_t *device_descriptor_callback(uint8_t speed)
{
    return device_descriptor;
}

static const uint8_t *config_descriptor_callback(uint8_t speed)
{
    return config_descriptor;
}

static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
{
    return device_quality_descriptor;
}

static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
{
    if (index > 5) {
        return NULL;
    }
    return string_descriptors[index];
}

const struct usb_descriptor composite_descriptor = {
    .device_descriptor_callback = device_descriptor_callback,
    .config_descriptor_callback = config_descriptor_callback,
    .device_quality_descriptor_callback = device_quality_descriptor_callback,
    .string_descriptor_callback = string_descriptor_callback
};


static void usbd_event_handler(uint8_t busid, uint8_t event)
{
    switch (event) {
        case USBD_EVENT_RESET:
            break;
        case USBD_EVENT_CONNECTED:
            break;
        case USBD_EVENT_DISCONNECTED:
            break;
        case USBD_EVENT_RESUME:
            break;
        case USBD_EVENT_SUSPEND:
            break;
        case USBD_EVENT_CONFIGURED:
            /* 启动Audio和Display的端点读取 */
            usbd_ep_start_read(busid, AUDIO_OUT_EP, audio_read_buffer, AUDIO_OUT_PACKET);
            usbd_ep_start_read(busid, DISPLAY_OUT_EP, display_read_buffer, MAX_DISP_PAYLOAD_SIZE);
            break;
        case USBD_EVENT_SET_REMOTE_WAKEUP:
            break;
        case USBD_EVENT_CLR_REMOTE_WAKEUP:
            break;
        default:
            break;
    }
}





/*************************************************************************************/
__attribute__((weak)) void usbd_graphic_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
    // USB_LOG_RAW("display out len:%d\r\n", (unsigned int)nbytes);
    usbd_ep_start_read(busid, ep, display_read_buffer, MAX_DISP_PAYLOAD_SIZE);
}
__attribute__((weak)) void usbd_graphic_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
    // USB_LOG_RAW("display in len:%d\r\n", (unsigned int)nbytes);
}

static struct usbd_endpoint display_out_ep = {
    .ep_addr = DISPLAY_OUT_EP,
    .ep_cb = usbd_graphic_bulk_out
};

static struct usbd_endpoint display_in_ep = {
    .ep_addr = DISPLAY_IN_EP,
    .ep_cb = usbd_graphic_bulk_in
};

struct usbd_interface *usbd_graphic_init_intf(struct usbd_interface *intf)
{
    
    intf->class_interface_handler = NULL;
    intf->class_endpoint_handler = NULL;
    intf->vendor_handler = NULL;
    intf->notify_handler = NULL;

    return intf;
}



/*************************************************************************************/
struct audio_entity_info audio_entity_table[] = {
    { .bEntityId = AUDIO_OUT_FU_ID,
      .bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT,
      .ep = AUDIO_OUT_EP 
    },
};

void usbd_audio_open(uint8_t busid, uint8_t intf)
{
    if (intf == 2) {
        audio_rx_flag = 1;
        usbd_ep_start_read(busid, AUDIO_OUT_EP, audio_read_buffer, AUDIO_OUT_PACKET);
#if USING_FEEDBACK == 1
        uint32_t feedback_value = AUDIO_FREQ_TO_FEEDBACK_FS(s_speaker_sample_rate);
        AUDIO_FEEDBACK_TO_BUF_FS(s_speaker_feedback_buffer, feedback_value);
        usbd_ep_start_write(busid, AUDIO_OUT_FEEDBACK_EP, s_speaker_feedback_buffer, FEEDBACK_ENDP_PACKET_SIZE);
#endif
        printf("Audio OPEN\r\n");
    }
}

void usbd_audio_close(uint8_t busid, uint8_t intf)
{
    if (intf == 2) {
        audio_rx_flag = 0;
        printf("Audio CLOSE\r\n");
    }
}

void usbd_audio_set_sampling_freq(uint8_t busid, uint8_t ep, uint32_t sampling_freq)
{
    if (ep == AUDIO_OUT_EP) {
        s_speaker_sample_rate = sampling_freq;
    }
}

uint32_t usbd_audio_get_sampling_freq(uint8_t busid, uint8_t ep)
{
    (void)busid;
    uint32_t freq = 0;
    if (ep == AUDIO_OUT_EP) {
        freq = s_speaker_sample_rate;
    }
    return freq;
}

__attribute__((weak)) void usbd_audio_out_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
    // USB_LOG_RAW("audio out len:%d\r\n", (unsigned int)nbytes);
    usbd_ep_start_read(busid, AUDIO_OUT_EP, audio_read_buffer, AUDIO_OUT_PACKET);
}

static struct usbd_endpoint audio_out_ep = {
    .ep_cb = usbd_audio_out_callback,
    .ep_addr = AUDIO_OUT_EP
};

#if USING_FEEDBACK == 1
void usbd_audio_iso_out_feedback_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
    uint32_t feedback_value = AUDIO_FREQ_TO_FEEDBACK_FS(s_speaker_sample_rate);
    AUDIO_FEEDBACK_TO_BUF_FS(s_speaker_feedback_buffer, feedback_value);
    usbd_ep_start_write(busid, AUDIO_OUT_FEEDBACK_EP, s_speaker_feedback_buffer, FEEDBACK_ENDP_PACKET_SIZE);
}

static struct usbd_endpoint audio_out_feedback_ep = {
    .ep_cb = usbd_audio_iso_out_feedback_callback,
    .ep_addr = AUDIO_OUT_FEEDBACK_EP
};
#endif



/*************************************************************************************/
__attribute__((weak)) void usbd_hid_int_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
    USB_LOG_RAW("hid int len:%d\r\n", (unsigned int)nbytes);
    hid_state = HID_STATE_IDLE;
}

static struct usbd_endpoint hid_in_ep = {
    .ep_cb = usbd_hid_int_callback,
    .ep_addr = HID_INT_EP
};


void usbd_hid_get_report(uint8_t busid, uint8_t intf, uint8_t report_id, uint8_t report_type, uint8_t **data, uint32_t *len)
{
    /*这个report非常关键, 没有就不能work*/
    (void)busid;
    (void)intf;
    (void)report_id;
    (void)report_type;
    if(report_id == 0x02) {
        (*data[0]) = 0x02;
        (*data[1]) = 0x05;
        *len = 2;
    }
    else if(report_id == 0x03) {
        (*data[0]) = 0x03;
        (*data[1]) = 0x05;
        *len = 2;
    }
}










/*************************************************************************************/
struct usbd_interface intf0;  // Display
struct usbd_interface intf1;  // Audio Control
struct usbd_interface intf2;  // Audio Streaming
struct usbd_interface intf3;  // hid


void usb_audio_display_composite_init(uint8_t busid, uintptr_t reg_base)
{
    board_init_usb_pins();



    /* 注册描述符 */
    usbd_desc_register(busid, &composite_descriptor);
    
    /* 添加Display接口 */
    usbd_add_interface(busid, usbd_graphic_init_intf(&intf0));
    usbd_add_endpoint(busid, &display_out_ep);
    usbd_add_endpoint(busid, &display_in_ep);
    
    /* 添加Audio接口 */
    usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf1, 0x0100, audio_entity_table, 1));
    usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf2, 0x0100, audio_entity_table, 1));
    usbd_add_endpoint(busid, &audio_out_ep);
#if USING_FEEDBACK == 1
    usbd_add_endpoint(busid, &audio_out_feedback_ep);
#endif

    /* 添加HID接口 */
    usbd_add_interface(busid, usbd_hid_init_intf(busid, &intf3, hid_report_desc, HID_REPORT_DESC_SIZE));
    usbd_add_endpoint(busid, &hid_in_ep);
    
    /* 初始化USB设备 */
    usbd_initialize(busid, reg_base, usbd_event_handler);
}





/*************************************************************************************/
/*
void usbd_audio_out_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
    // USB_LOG_RAW("audio out len:%d\r\n", (unsigned int)nbytes);
    do_trace2("composite.c", __LINE__, __func__, nbytes, "<= nbytes");
    usbd_ep_start_read(busid, AUDIO_OUT_EP, audio_read_buffer, AUDIO_OUT_PACKET);
}


void usbd_graphic_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
    // USB_LOG_RAW("disp out len:%d\r\n", (unsigned int)nbytes);
    do_trace2("composite.c", __LINE__, __func__, nbytes, "<= nbytes");
    usbd_ep_start_read(busid, ep, display_read_buffer, MAX_DISP_PAYLOAD_SIZE);
}

void usbd_graphic_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
    // Display IN端点回调 
}

void usbd_hid_int_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
    hid_state = HID_STATE_IDLE;
}
*/